import 'dart:async';

import 'package:flutter/services.dart';
import 'package:mqtt_client/mqtt_client.dart';
import 'package:mqtt_client/mqtt_server_client.dart';
import 'package:syn_4s/core/utils/event_bus.dart';

import '../constants/event_code.dart';

class MqttManager {

  late final MqttServerClient client;
  bool isChange = false;
  // final client =
  //     MqttServerClient.withPort("192.168.1.197", "flutter_client", 1883);

  // MqttServerClient.withPort("synergosiot.ddns.net", "flutter_client", 2883);

  // 单例实例
  static final MqttManager _instance = MqttManager._internal();

  // 私有构造函数
  MqttManager._internal() {
    print("_internal");
    client = MqttServerClient.withPort("broker.emqx.io", "deviced_111", 1883);
    listenInt((event) {
      if (event == eventSite) {
        isChange = true;
        // manager.closeConnect();
        // manager.connect();
      }
    });
    // MqttServerClient.withPort("184.168.123.134", "mqttx_1dce9048", 1883);
    // 初始化配置在这里设置
  }

  // 工厂构造函数
  factory MqttManager() {
    return _instance;
  }

  connect() async {
    print(client.connectionStatus?.state);
    if (client.connectionStatus?.state == MqttConnectionState.connected) {
      if (isChange) {
        isChange = false;
        closeConnect();
        connect();
      }
      return;
    }
    String projCode = "CNCE";
    // String projCode = await SPUtils.get(keyProjCode) ?? "";
    client.logging(on: true);
    client.onConnected = onConnected;
    client.onDisconnected = onDisconnected;
    client.onUnsubscribed = onUnsubscribed;
    client.onSubscribed = onSubscribed;
    client.onSubscribeFail = onSubscribeFail;
    client.pongCallback = pong;
    // 设置心跳保持时间为 60 秒，替换MqttConnectMessage().keepAliveFor(60)
    client.keepAlivePeriod = 60;

    final connMess = MqttConnectMessage()
        .withClientIdentifier("deviced_111")
        // .authenticateAs("mqttUser", "mqtt@1234")
        .withWillTopic("synportalow/event/check/pushmsg/CNCE")
        .withWillMessage('My Will message')
        .startClean()
        .withWillQos(MqttQos.atLeastOnce);
    client.connectionMessage = connMess;

    try {
      print('Connecting');
      await client.connect();
    } catch (e) {
      print('Exception: $e');
      client.disconnect();
    }

    if (client.connectionStatus?.state == MqttConnectionState.connected) {
      // 属性'state'不能被无条件访问，因为接收方可以是'null'。
      print('EMQX client connected');
      client.updates?.listen((List<MqttReceivedMessage<MqttMessage>> c) {
        final MqttPublishMessage message = c[0].payload as MqttPublishMessage;
        final payload =
            MqttPublishPayload.bytesToStringAsString(message.payload.message);
        print('接收消息:$payload from topic: ${c[0].topic}>');
      });

      // client.published?.listen((MqttPublishMessage message) {
      //   print('published');
      //   final payload =
      //       MqttPublishPayload.bytesToStringAsString(message.payload.message);
      //   print(
      //       'Published message: $payload to topic: ${message.variableHeader?.topicName}');
      // });
    } else {
      print(
          'EMQX client connection failed - disconnecting, status is ${client.connectionStatus}');
      client.disconnect();
    }
    client.subscribe(
        "synportalow/event/check/pushmsg/CNCE", MqttQos.atLeastOnce);
    // "synportalow/event/check/pushmsg/${projCode}", MqttQos.atLeastOnce);
  }

  closeConnect() {
    client.disconnect();
  }

  Future<List<int>> loadBytes(String assetPath) async {
    ByteData data = await rootBundle.load(assetPath);
    List<int> bytes = data.buffer.asUint8List();
    return bytes;
  }
}

// 连接成功
void onConnected() {
  print('Connected');
}

// 连接断开
void onDisconnected() {
  print('Disconnected');
}

// 订阅主题成功
void onSubscribed(String topic) {
  print('Subscribed topic: $topic');
}

// 订阅主题失败
void onSubscribeFail(String topic) {
  print('Failed to subscribe topic: $topic');
}

// 成功取消订阅  topic可空
void onUnsubscribed(String? topic) {
  print('Unsubscribed topic: $topic');
}

// 收到 PING 响应
void pong() {
  print('Ping response client callback invoked');
}
